home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / suck-2.6 / suck-2 / suck-2.6.3 / both.c next >
C/C++ Source or Header  |  1996-03-06  |  8KB  |  358 lines

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <netdb.h>
  4. #include <ctype.h>
  5. #include <string.h>
  6. #include <netinet/in.h>
  7. #include <sys/socket.h>
  8. #include <arpa/inet.h>
  9. #include <errno.h>
  10. #include <stdarg.h>
  11. #include <limits.h>
  12. #include "config.h"
  13. #include "both.h"
  14.  
  15. #ifdef TIMEOUT
  16. #include <sys/time.h>
  17. #include <sys/types.h>
  18. #endif
  19.  
  20. #ifdef MYSIGNAL
  21. #include <signal.h>
  22. #endif
  23.  
  24. /*-----------------------------------------------------*/
  25. /* get next number in string */
  26. char *number(char *sp, int *intPtr) {
  27.     int start, end;
  28.     char c;
  29.     char *retval;
  30.  
  31.     if(sp==NULL) {
  32.         *intPtr=0; 
  33.         retval = sp;
  34.     }
  35.     else {
  36.         /* skip any leading spaces */
  37.         start = 0;
  38.         while(sp[start] == ' ') {
  39.             start++;
  40.         }
  41.         end = start;
  42.         while(isdigit(sp[end])) {
  43.             end++;
  44.         }
  45.         /* now we have the numbers width*/
  46.  
  47.         c=sp[end];    /* save off the character */
  48.         sp[end]='\0';    /* truncate nr so sscanf works right */
  49.         sscanf(&sp[start],"%d",intPtr);
  50.         sp[end]=c;    /* restore it back */
  51.  
  52.         /* if at EOS return the NULL, else skip space */
  53.         retval = (sp[end] == '\0') ? sp+end : sp+(++end);
  54.     }
  55.     return retval;
  56. }
  57. /*---------------------------------------------*/
  58. struct hostent *get_hostent(char *host) {
  59.     struct in_addr saddr;
  60.     int c;
  61.     struct hostent *hi = NULL;
  62.  
  63.     if(host==NULL) { 
  64.         error_log(ERRLOG_REPORT,"No hostname given !\r\n"); 
  65.     }
  66.     else {
  67.         c=*host;
  68.         if(isdigit(c)) {
  69.              saddr.s_addr = inet_addr(host); 
  70.              hi = gethostbyaddr((char *)&saddr,sizeof(struct in_addr),AF_INET);
  71.         }
  72.         else {
  73.             hi = gethostbyname(host);
  74.         }
  75.     }
  76.     return hi;
  77. }
  78. /*--------------------------------------------*/
  79. int connect_to_nntphost(char *host, struct hostent **hi, FILE *msgs) {
  80.     char *ptr;
  81.     struct in_addr *aptr;
  82.     struct in_addr saddr;
  83.     struct sockaddr_in address;
  84.     int sockfd = -1;
  85.  
  86.     /* Find the internet address of the NNTP server */
  87.      *hi = get_hostent(host);
  88.      if(*hi == NULL) {
  89.         error_log(ERRLOG_REPORT,"%s: ",host);
  90.           MyPerror("Could not get host information");
  91.      }
  92.     else {
  93.         fprintf(msgs, "Official host name: %s\r\n", (*hi)->h_name);
  94.          while((ptr = *((*hi)->h_aliases)) != NULL) {
  95.             fprintf(msgs, "Alias %s\r\n", ptr );
  96.             (*hi)->h_aliases++;
  97.         }
  98.          if((*hi)->h_addrtype != AF_INET) {
  99.               error_log(ERRLOG_REPORT,"Unsupported address type.\n" );
  100.         }
  101.         else {
  102.             while((aptr = (struct in_addr *)*((*hi)->h_addr_list)++) != NULL) {
  103.                 saddr = *aptr;
  104.                 fprintf(msgs, "Address: %s\r\n", inet_ntoa(*aptr));
  105.             }
  106.  
  107.             /* Create a socket */
  108.              if((sockfd = socket( AF_INET, SOCK_STREAM, SOCKET_PROTOCOL)) == -1) {
  109.                 MyPerror("Socket failed:");
  110.             }
  111.             else { 
  112.                 address.sin_family = AF_INET;
  113.                 address.sin_port = htons(119);  /* NNTP port */
  114.                 address.sin_addr= saddr;
  115.  
  116.                 /* Establish a connection */
  117.                 if(connect(sockfd, (struct sockaddr *)&address, sizeof address ) == -1) {
  118.                     MyPerror("Connect failed:");
  119.                     close(sockfd);
  120.                     sockfd = -1;
  121.                 }
  122.                 else {
  123.                     fprintf(msgs,"Connected to %s\r\n",(*hi)->h_name);
  124.                 }
  125.             }
  126.         }
  127.     }
  128.     return sockfd;
  129. }
  130. /*----------------------------------------------------------------*/
  131. int sputline(int fd, char *outbuf) {
  132.     
  133. #ifdef DEBUG1
  134.     do_debug("\nSENT: %s", outbuf);
  135. #endif
  136.     return send(fd, outbuf, strlen(outbuf), 0);
  137. }
  138. /*-------------------------------------------------------------*/
  139. #ifdef DEBUG
  140. void do_debug(char *fmt, ...) {
  141.  
  142.     FILE *fptr = NULL;
  143.     va_list args;
  144.  
  145.     if((fptr = fopen(N_DEBUG, "a")) == NULL) {
  146.         fptr = stderr;
  147.     }
  148.         
  149.     va_start(args, fmt);
  150.     vfprintf(fptr, fmt, args);
  151.     va_end(args);
  152.  
  153.     if(fptr != stderr) {
  154.         fclose(fptr);
  155.     }
  156. }
  157. #endif
  158. /*------------------------------------------------------------*/
  159. void MyPerror(char *message) {
  160.  
  161. #ifdef DEBUG    
  162.     do_debug("%d: %s\n", errno, message);
  163. #endif
  164.     /* can't just use perror, since it goes to stderr */
  165.     /* and I need to route it to my errlog */
  166.     /* so I have to recreate perror's format */
  167.     error_log(ERRLOG_REPORT, "%s: %s\n", message, strerror(errno));
  168. }    
  169. /*-----------------------------------------------------------*/
  170. int sgetline(int fd, char **inbuf) {
  171.  
  172.     static char buf[MAXLINLEN+MAXLINLEN+6];
  173.     static char *start = buf;
  174.     static char *eob = buf;        /* end of buffer */
  175.     int ret, i, len;
  176.     char *ptr;
  177.  
  178. #ifdef TIMEOUT
  179.     fd_set myset;
  180.     struct timeval mytimes;
  181. #endif
  182.     ret = 0;
  183.     ptr = NULL;
  184.  
  185.     if(eob == start || (ptr = strstr(start,"\r\n")) == NULL) {
  186.         /* TEST for not a full line in buffer */    
  187.         /* the eob == start test is needed in case the buffer is */
  188.         /* empty, since we don't know what is in it. */
  189.  
  190.         i = eob-start;     /* length of partial line in buf */
  191.         if((eob - buf) > MAXLINLEN) {
  192. #ifdef DEBUG1
  193.             do_debug("SHIFTING BUFFER\n");
  194. #endif
  195.             /* not enuf room in buffer for a full recv */
  196.             bcopy(start, buf, i);        /* move to start of buf */
  197.             eob = buf + i;
  198.             *eob = '\0';
  199.             start = buf;            /* reset pointers */
  200.         }
  201.         len = i;
  202.         /* try to get a line in, up to maxlen */
  203.         do {
  204. #ifdef TIMEOUT
  205.             /* handle timeout value */
  206.             FD_ZERO(&myset);
  207.             FD_SET(fd, &myset);
  208.             mytimes.tv_sec = TIMEOUT;
  209.             mytimes.tv_usec = 0;
  210.     
  211. #ifdef MYSIGNAL
  212.             signal_block(MYSIGNAL_BLOCK);
  213.             /* block so we can't get interrupted by our signal defined in config.h */
  214. #endif
  215.  
  216.             if((i = select(FD_SETSIZE, &myset, (fd_set *) NULL, (fd_set *) NULL, &mytimes)) == 1) {
  217.                 i = recv(fd, eob, MAXLINLEN-len, 0);    /* get line */
  218.             }
  219.             else {
  220.                 /* error */
  221.                 if(i == 0) {
  222.                     /* no bytes available */
  223.                     errno =  ETIMEDOUT;
  224.                 }
  225.                 i = -1;
  226.             }
  227. #else 
  228.             i = recv(fd, eob, MAXLINLEN-len, 0);    /* get line */
  229. #endif
  230. #ifdef DEBUG1
  231.             do_debug("\nSelect/Recv returned %d", i);
  232. #endif
  233. #ifdef MYSIGNAL
  234.             signal_block(MYSIGNAL_UNBLOCK);
  235.             /* we are done, now unblock it */
  236. #endif
  237.  
  238.             if(i < 1) {
  239.                 if(i == 0) {
  240.                     /* in case recv has no data */
  241.                     errno = ENODATA;
  242.                 }
  243.                 MyPerror("Socket error");
  244.                 ret = -1;
  245.             }
  246.             else {
  247.                 eob += i;    /* increment buffer end */
  248.                 *eob = '\0';    /* NULL terminate it  */
  249. #ifdef DEBUG1
  250.                 do_debug("\nGOT: %.*s",i,eob-i);
  251. #endif 
  252.                 len += i;                
  253.                 ptr = strstr(start, "\r\n");        
  254.             }
  255.         } while(ptr == NULL && len < MAXLINLEN && ret == 0);
  256.     }
  257.     if(ptr != NULL) {
  258.         /* we have a full line left in buffer */
  259.         *ptr++ = '\n';    /* change \r\n to just \n */
  260.         *ptr++ = '\0';    /* null terminate */
  261.         *inbuf = start;
  262.         ret = (ptr-1) - start;    /* length of string */
  263.         start = ptr;     /* skip \r\n */
  264.         if(eob == start) {
  265.             /* nothing left in buffer, reset pointers to start of buffer */
  266.             /* to give us a full buffer to receive next data into */
  267.             /* hopefully doing this will mean less buffer shifting */
  268.             /* meaning faster receives */
  269.             eob = start = buf;
  270. #ifdef DEBUG1
  271.             do_debug("Empty buffer, resetting to start\n");
  272. #endif
  273.         }
  274.     }
  275.     else if(ret == 0) {
  276.         /* partial line in buffer */
  277.         /* null terminate */
  278.         *eob = '\0';
  279.         *inbuf = start;
  280.         ret = (eob-1) - start;    /* length of string */
  281.         start = ++eob;    /* point both past end */
  282.     }
  283. #ifdef DEBUG1
  284.     if(ret > 0) {
  285.         do_debug("\nRETURNING len %d: %s", ret, *inbuf);
  286.     }
  287.     else {
  288.         do_debug("\nRETURNING error, ret = %d", ret);
  289.     }
  290. #endif  
  291.     return ret;
  292. }        
  293. /*----------------------------------------------------*/
  294. #ifdef MYSIGNAL
  295. void signal_block(int action) {
  296.  
  297.     static sigset_t blockers;
  298.     static do_block = FALSE;
  299.  
  300.     switch(action) {
  301.         case MYSIGNAL_SETUP:
  302.             sigemptyset(&blockers);
  303.             if(sigaddset(&blockers, MYSIGNAL) == -1) {
  304.                 do_block = FALSE;
  305.                 error_log(ERRLOG_REPORT, "Unable to block signal %d\n", MYSIGNAL);
  306.             }
  307.             else {
  308.                 do_block = TRUE;
  309.             }
  310.             break;
  311.         case MYSIGNAL_BLOCK:
  312.             if(do_block == TRUE) {
  313.                 sigprocmask(SIG_BLOCK, &blockers, NULL);
  314.             }
  315.             break;
  316.         case MYSIGNAL_UNBLOCK:
  317.             if(do_block == TRUE) {
  318.                 sigprocmask(SIG_UNBLOCK, &blockers, NULL);
  319.             }
  320.             break;
  321.     }
  322. }
  323. #endif
  324. /*-------------------------------------------------------------------*/
  325. void error_log(int mode, char *fmt, ...) {
  326.  
  327.     /* if we have been passed a file, report all errors to that file */
  328.     /* else report all errors to stderr */
  329.     /* handle printf type formats, hence the varargs stuff */
  330.  
  331.     FILE *fptr = NULL;
  332.     va_list args;
  333.     static char errfile[_POSIX_PATH_MAX] = { '\0' };
  334.  
  335.     va_start(args, fmt);    /* set up args */
  336.     
  337.     switch(mode) {
  338.       case ERRLOG_SET_FILE:
  339.         strcpy(errfile,fmt);
  340.         break;
  341.       case ERRLOG_SET_STDERR:
  342.         errfile[0] = '\0';
  343.         break;
  344.       case ERRLOG_REPORT:
  345.         if(errfile[0] == '\0' || (fptr = fopen(errfile, "a")) == NULL) {
  346.             fptr = stderr;
  347.         }
  348.         vfprintf(fptr, fmt, args);
  349.  
  350.         if(fptr != stderr) {
  351.             fclose(fptr);
  352.         }
  353.         break;
  354.     }
  355.     va_end(args);        /* so we can return normally */
  356.     return;
  357. }
  358.